package plp.orientadaObjetos2.memoria;

import java.util.ArrayList;
import java.util.List;

import plp.expressions2.memory.VariavelNaoDeclaradaException;
import plp.orientadaObjetos1.comando.Procedimento;
import plp.orientadaObjetos1.declaracao.procedimento.DecProcedimento;
import plp.orientadaObjetos1.declaracao.variavel.DecVariavel;
import plp.orientadaObjetos1.excecao.declaracao.ProcedimentoNaoDeclaradoException;
import plp.orientadaObjetos1.expressao.leftExpression.Id;
import plp.orientadaObjetos1.memoria.DefClasse;
import plp.orientadaObjetos1.util.Tipo;
import plp.orientadaObjetos2.declaracao.DecConstrutor;
import plp.orientadaObjetos2.declaracao.funcao.DecFuncao;

public class DefClasseOO2 extends DefClasse {

	/**
	 * Nome super classe
	 */
	private Id nomeSuperClasse;
	
	/**
	 * Consturtor
	 */
	private DecConstrutor construtor;

	/**
	 * Funcoes
	 */
	private List<DecFuncao> funcoes;

	/**
	 * Esta classe eh nativa?
	 */
	private boolean nativa;

	public DefClasseOO2(Id idClasse, Id nomeSuperClasse,DecVariavel decVariavel,
			DecConstrutor construtor, DecProcedimento decProcedimento, List<DecFuncao> funcoes) {
		super(idClasse, decVariavel, decProcedimento);
		this.nomeSuperClasse = nomeSuperClasse;
		this.construtor = construtor;
		this.funcoes = new ArrayList<DecFuncao>(funcoes);
	}

	public DefClasseOO2(Id idClasse, Id nomeSuperClasse,DecVariavel decVariavel,
						DecConstrutor construtor, DecProcedimento decProcedimento,
						List<DecFuncao> funcoes, boolean nativa) {
		super(idClasse, decVariavel, decProcedimento);
		this.nomeSuperClasse = nomeSuperClasse;
		this.construtor = construtor;
		this.funcoes = new ArrayList<DecFuncao>(funcoes);
		this.nativa = nativa;
	}

	public DecConstrutor getConstrutor() {
		return construtor;
	}

	public void setConstrutor(DecConstrutor construtor) {
		this.construtor = construtor;
	}

	/**
	 * @return the nomeSuperClasse
	 */
	public Id getNomeSuperClasse() {
		return nomeSuperClasse;
	}

	/**
	 * @param nomeSuperClasse the nomeSuperClasse to set
	 */
	public void setNomeSuperClasse(Id nomeSuperClasse) {
		this.nomeSuperClasse = nomeSuperClasse;
	}

	public List<DecFuncao> getFuncoes() {
		return funcoes;
	}

	public DecFuncao getFuncao(Id nomeFuncao) throws FuncaoNaoDeclaradaException  {
		DecFuncao funcao = null;
		List<DecFuncao> funcoes = this.getFuncoes();
		for (DecFuncao decFuncao : funcoes) {
			if(decFuncao.getNome().equals(nomeFuncao)){
				funcao = decFuncao;
				break;
			}
		}
		if(funcao == null){
			throw new FuncaoNaoDeclaradaException(nomeFuncao);
		}
		return funcao;
	}

	
	@Override
	public DecVariavel getDecVariavel() {
		return super.getDecVariavel();
	}

	@Override
	public Procedimento getMetodo(Id idMetodo)
			throws ProcedimentoNaoDeclaradoException {
		if(this.decProcedimento == null){
			throw new ProcedimentoNaoDeclaradoException(idMetodo);
		}
		return super.getMetodo(idMetodo);
	}

	@Override
	public Tipo getTipoAtributo(Id idAtributo)
			throws VariavelNaoDeclaradaException {
		if(this.decVariavel == null){
			throw new VariavelNaoDeclaradaException(idAtributo);
		}
		return super.getTipoAtributo(idAtributo);
	}

	public boolean isNativa() {
		return nativa;
	}

}
